Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[charts] Support animation #9926

Merged
merged 26 commits into from
Oct 19, 2023
Merged

[charts] Support animation #9926

merged 26 commits into from
Oct 19, 2023

Conversation

alexfauquette
Copy link
Member

@alexfauquette alexfauquette commented Aug 4, 2023

The current solution is to use react-spring transition.

To let Argos pass, I added a config that disabled the animation.

The demonstration: https://deploy-preview-9926--material-ui-x.netlify.app/x/react-charts/bars/#animation

It still suffers a small bug

In responsive mode, bars seem to come from the point (0, 0) instead of just growing from bottom to top.

It's because in responsive mode, the width of the chart is computed from its parent in a useEffect. So before the useEffect is done, the chart width is set by default to 0.

So from the point of view of useTransition the initial point is (0, 0) whereas it should be the correct one with height set to 0.

I think I will just block children's rendering at the first rendering in responsive. But if you have a better idea

@alexfauquette alexfauquette marked this pull request as draft August 4, 2023 12:37
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Aug 4, 2023
@github-actions
Copy link

github-actions bot commented Aug 4, 2023

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@mui-bot
Copy link

mui-bot commented Aug 4, 2023

Deploy preview: https://deploy-preview-9926--material-ui-x.netlify.app/

Updated pages:

Generated by 🚫 dangerJS against 1ff3021

@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Aug 4, 2023
@alexfauquette alexfauquette added the component: charts This is the name of the generic UI component, not the React module! label Aug 4, 2023
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Aug 7, 2023
@github-actions
Copy link

github-actions bot commented Aug 7, 2023

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@@ -117,12 +124,28 @@ export function BarElement(props: BarElementProps) {
};
const classes = useUtilityClasses(ownerState);

const spring = useSpring({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know if our competitors are bundling a third party animation library like this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Nivo is using spring
  • Rechart is using react-transition-group -> sounds limited for animating props modification
  • Echarts has its own set of function -> mAybe to much work for now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK
One advantage of react-transition-group is that we already bundle it for the pickers so most users will have it in their bundle anyway.
But if it's too limited, I agree that going for react-spring can be interesting.

Copy link
Member Author

@alexfauquette alexfauquette Aug 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From What I understand, react-transition-group is mostly to create transition during the creation/deletion of components. But here we will also be interested in props modification. For example adding a bar means pushing all the other ones to a new position

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW in my last projects I've always been using this minimalistic animation function, I was very satisfied with the choice because it's very simple to understand & tune. Adding a wrapper around it to make it into a hook should be trivial.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spend some time to think about it, but will go with react-spring for now, more for their animated elements than for the interpolation functions. It allows to pass style as usual without having react re-render

https://www.react-spring.dev/docs/concepts/animated-elements

Copy link
Member

@flaviendelangle flaviendelangle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nice addition and with a very little amount of new code.

If we agree to use react-spring (cc @LukasTy), then for me the only thing missing is a prop to disable the animation (because that's clearly something not everybody wants.
And disable it on the sparkline.

@@ -64,6 +65,7 @@ export const BarElementPath = styled('rect', {
export type BarElementProps = Omit<BarElementOwnerState, 'isFaded' | 'isHighlighted'> &
React.ComponentPropsWithoutRef<'path'> & {
highlightScope?: Partial<HighlightScope>;
yOrigine: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/yOrigine/yOrigin/

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might admit I do not understand this comment 🙈

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, that's the sed CLI command way to perform a substitution, replacing yOrigine with yOrigin. "Origine" is French, the English word doesn't take a final e.

@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Sep 28, 2023
@alexfauquette alexfauquette marked this pull request as ready for review September 29, 2023 08:42
Signed-off-by: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com>
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Sep 29, 2023
@github-actions
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

const { series, stackingGroups } = seriesData;
const { xAxis, yAxis, xAxisIds, yAxisIds } = axisData;
const defaultXAxisId = xAxisIds[0];
const defaultYAxisId = yAxisIds[0];

const data = stackingGroups.flatMap(({ ids: groupIds }, groupIndex) => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That can seem to be a huge modification, but it's "just" moving the computation of rectangle position at the top such that those coordinates can be passed to the useTransition

@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Oct 17, 2023
Copy link
Contributor

@noraleonte noraleonte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing addition 🎉 💙

docs/data/charts/bars/bars.md Outdated Show resolved Hide resolved
docs/data/charts/bars/bars.md Outdated Show resolved Hide resolved
docs/data/charts/bars/bars.md Outdated Show resolved Hide resolved
@alexfauquette
Copy link
Member Author

About the animation starting at (0, 0) point, I confirm it get fixed by modifying the responsive container as follows. The idea being that if we have no width/height it's useless to do the upcoming computation since we will need to do them back for the next render when we get access to the correct sizing of the component.

 <ResizableContainer ref={containerRef} ownerState={{ width: inWidth, height: inHeight }}>
+      {width && height ? (
        <ChartContainer {...other} width={width} height={height} ref={ref} />
+      ) : null}
    </ResizableContainer>

Copy link
Member

@LukasTy LukasTy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution looks very elegant. 👍
One concern worth taking note of is that this additional library is currently 1/3 of the whole charts package in size. 🙈

General question:

  1. Have you considered having the animation toggle top level (on the container), because I imagine that eventually we'll animate everything, even the tooltip movement. 🤔
  2. Consider having a default for disableAnimation or animate, which would respect the prefers-reduced-motion os setting.
    Similar to how we handle reduceAnimations on pickers.
  3. Providing animation customization is probably a separate issue and planned for the future?
  4. Have you looked over the argos differences? Some of those seem concerning and the result new doc page actually has overflowing bars. 🤔

docs/data/charts/bars/bars.md Outdated Show resolved Hide resolved
docs/data/charts/bars/bars.md Outdated Show resolved Hide resolved
packages/x-charts/src/BarChart/BarPlot.tsx Outdated Show resolved Hide resolved
test/regressions/index.test.js Outdated Show resolved Hide resolved
packages/x-charts/src/BarChart/BarPlot.tsx Outdated Show resolved Hide resolved
packages/x-charts/src/BarChart/BarPlot.tsx Outdated Show resolved Hide resolved
packages/x-charts/src/BarChart/BarPlot.tsx Outdated Show resolved Hide resolved
packages/x-charts/src/BarChart/BarPlot.tsx Outdated Show resolved Hide resolved
packages/x-charts/src/BarChart/BarPlot.tsx Outdated Show resolved Hide resolved
packages/x-charts/src/BarChart/BarPlot.tsx Outdated Show resolved Hide resolved
@alexfauquette
Copy link
Member Author

One concern worth taking note of is that this additional library is currently 1/3 of the whole charts package in size. 🙈

Yes, but it allows us to move forward. Maybe removing it for a lighter solution when we get a large userbase.

  1. Have you considered having the animation toggle top level (on the container), because I imagine that eventually we'll animate everything, even the tooltip movement. 🤔

Good idea, but I'm not sure it's worth it.

  • Most of our users might use a single component, so they don't care.
  • If you're using composition, I assume you want fine-grained management
  1. Consider having a default for disableAnimation or animate, which would respect the prefers-reduced-motion os setting.
    Similar to how we handle reduceAnimations on pickers.

@react-spring/web already offers useReducedMotion() which remove animation. It's best that user call it once in their app. I thaught it was documented. I will add a sentence about it.

  1. Providing animation customization is probably a separate issue and planned for the future?

Not really. In the issue, someone said that they just use default animation. We could consider providing a way to customize react-spring configuration, to get faster/slower animation. But more advanced customization seems to be a path in a difficult problem for no reward.

  1. Have you looked over the argos differences? Some of those seem concerning and the result new doc page actually has overflowing bars. 🤔

What do you mean by "overflowing"?

For this kind of diff, the SVG edges definition is quite vague about how they are computed. So I assume that modifying the CPU usage can lead to edge errors.

image

alexfauquette and others added 5 commits October 18, 2023 14:31
Co-authored-by: Nora <72460825+noraleonte@users.noreply.github.com>
Co-authored-by: Lukas <llukas.tyla@gmail.com>
Signed-off-by: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com>
docs/data/charts/bars/bars.md Show resolved Hide resolved
docs/data/charts/bars/bars.md Outdated Show resolved Hide resolved
@mui mui deleted a comment from alexfauquette Oct 18, 2023
@LukasTy
Copy link
Member

LukasTy commented Oct 18, 2023

The latest Argos changes seem strange... As if the explicit skipAnimation definition no longer works... 🤷

@alexfauquette
Copy link
Member Author

As if the explicit skipAnimation definition no longer works... 🤷

Yes, Argos use global settings and useReducedMotion override it.

I modified the hook such that it removes animation for users with a11y issue but do nothing otherwise

@alexfauquette
Copy link
Member Author

It works :)

@LukasTy
Copy link
Member

LukasTy commented Oct 18, 2023

What do you mean by "overflowing"?

I think that the overflow regression issue might be coming from the change of precision in the translate coordinates. 🤔

Current release:

Screenshot 2023-10-18 at 18 31 44

This PR

Screenshot 2023-10-18 at 18 32 21

Copy link
Member

@LukasTy LukasTy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! 💯
The precision question can be addressed separately. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: charts This is the name of the generic UI component, not the React module! new feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants